;; The first three lines of this file were inserted by DrRacket. They record metadata
;; about the language level of this file in a form that our tools can easily process.
#reader(lib "htdp-intermediate-lambda-reader.ss" "lang")((modname u4-huebung-a6-plain) (read-case-sensitive #t) (teachpacks ((lib "image.ss" "teachpack" "htdp"))) (htdp-settings #(#t constructor repeating-decimal #f #t none #f ((lib "image.ss" "teachpack" "htdp")))))
;; example colors
(define red       (make-color 255 0 0))
(define green     (make-color 0 255 0))
(define blue      (make-color 0 0 255))
(define green-ish (make-color 0 240 0))

;; example pictures
;; (define back        {insert chromakey_back.png here})
;; (define front-foto  {insert chromakey_front-foto.png here})
;; (define front-plain {insert chromakey_front-plain.png here})
;; (define front-real  {insert chromakey_front-real.png here})



;; 6.1
;; contract:    color-similarity: color color (color color -> number) -> number
;; description: Gets two colors and a procedure. Compares the colors by means of said procedure.
;; example:     (color-similarity (make-color 123 123 123) (make-color 123 123 123) naive) -> 1

(define (color-similarity color1 color2 comparer)
  (comparer color1 color2))

;; Tests
(check-expect (color-similarity green red simple) 0)
(check-expect (color-similarity green green-ish naive) 0)



;; 6.1.1
;; contract:    naive: color color -> number
;; description: Gives back the difference of two colors. Either 1 if identical or else 0.
;; example:     (naive (make-color 123 123 123) (make-color 123 123 123)) -> 1

(define (naive color1 color2)
  (cond [(and (= (color-red   color1) (color-red   color2))
              (= (color-green color1) (color-green color2))
              (= (color-blue  color1) (color-blue  color2)))
         1]
        [else 0]))

;; Tests
(check-expect (naive green green) 1)
(check-expect (naive green green-ish) 0)



;; 6.1.2
;; contract:    simple: color color -> number
;; description: Definite the difference of two colors in numbers between 0 and 1. Larger means more likeness.
;; example:     (simple (make-color 0 0 10) (make-color 0 20 40)) -> ~ 0.88

(define (simple color1 color2)
  (local (
          ;; calculates the maximal difference between the color-elements of 2 colors.
          (define max-diff (max (abs (- (color-red   color1) (color-red   color2)))
                                (abs (- (color-green color1) (color-green color2)))
                                (abs (- (color-blue  color1) (color-blue  color2))))))
    
    (cond [(= 0 max-diff) 1]
          [else (- 1 (/ max-diff 255))])))

;; Tests
(check-expect (simple green green) 1)
(check-expect (simple green red) 0)
(check-within (simple green green-ish) 0.94 0.01)



;; 6.2
;; contract:    chroma-keying: image image color number -> image
;; description: Replaces the foreground picture with the bg picture, if that part is in the threshold limit of the key.
;; example:     (chroma-keying (image with green parts) (red image) green 0.3) -> (first image, green parts replaced with red)

(define (chroma-keying background-picture foreground-picture key threshold)
  (local (
          ;; defines the colorlists of the pictures
          (define loc-bg (image->color-list background-picture))
          (define loc-fg (image->color-list foreground-picture))
          
          ;; contract:    replace: (listof color) (listof color) -> (listof color) 
          ;; description: Replaces colors from the foreground with the bg, when they are in the threshold limit of key.
          ;; example:     (replace (list green blue green) (list red red red)) -> (list green blue green) if key = red
          (define (replace loc-bg loc-fg)
            (cond [(empty? loc-bg) empty]
                  [else
                   (cons (cond [(<= (- 1 (simple key (first loc-fg))) threshold) (first loc-bg)]
                               [else (first loc-fg)])
                         (replace (rest loc-bg) (rest loc-fg)))])))
    
    (color-list->image (replace loc-bg loc-fg) (image-width foreground-picture) (image-height foreground-picture) 0 0)))


;; (chroma-keying back front-plain (make-color  67 255  0) 0.01)
;; (chroma-keying back front-real  (make-color 117 202 73) 0.2)
;; (chroma-keying back front-foto  (make-color  91 188 81) 0.2)

;; Tests
(define blue-blue-pxl  (color-list->image (list blue  blue) 1 2 0 0))
(define green-red-pxl  (color-list->image (list green red ) 1 2 0 0))
(define green-blue-pxl (color-list->image (list green blue) 1 2 0 0))
  
(check-expect (chroma-keying blue-blue-pxl green-red-pxl red 0.01) green-blue-pxl)
(check-expect (chroma-keying blue-blue-pxl green-red-pxl blue 0.01) green-red-pxl)